﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using JetBrains.Annotations;
#if TASKSUPPORT
using System.Threading.Tasks;
#endif
using MugenMvvmToolkit.Models;

namespace MugenMvvmToolkit.Interfaces
{
    /// <summary>
    ///     Represents a validator.
    /// </summary>
    public interface IValidator : IDisposable, IObservable,
#if !NODATAERROR
 IDataErrorInfo
#endif
#if !NONOTIFYDATAERROR
 INotifyDataErrorInfo
#endif
    {
        /// <summary>
        /// Indicates that can be only once instance of this validator.
        /// </summary>
        bool IsUnique { get; }

        /// <summary>
        ///     Gets the initialized state of the validator.
        /// </summary>
        bool IsInitialized { get; }

#if !NONOTIFYDATAERROR
        /// <summary>
        /// Gets or sets the value, that indicates that the validator will be validate property on changed. Default is true.
        /// </summary>
        bool ValidateOnPropertyChanged { get; set; }
#endif
        /// <summary>
        ///     Gets the validator context.
        /// </summary>
        IValidatorContext Context { get; }

        /// <summary>
        ///     Checks to see whether the validator can validate objects of the specified IValidatorContext.
        /// </summary>
        bool CanValidate([NotNull]IValidatorContext validatorContext);

        /// <summary>
        ///     Initializes the current validator using the specified <see cref="IValidatorContext" />.
        /// </summary>
        /// <param name="context">
        ///     The specified <see cref="IValidatorContext" />.
        /// </param>
        void Initialize([NotNull]IValidatorContext context);

#if !NODATAERROR
        /// <summary>
        ///     Gets the validation errors for a specified property or for the entire entity.
        /// </summary>
        /// <returns>
        ///     The validation errors for the property or entity.
        /// </returns>
        /// <param name="propertyName">
        ///     The name of the property to retrieve validation errors for; or null or <see cref="F:System.String.Empty" />, to retrieve entity-level errors.
        /// </param>
        [NotNull, Pure]
        IEnumerable GetErrors([CanBeNull]string propertyName);
#endif

        /// <summary>
        ///     Gets the all validation errors.
        /// </summary>
        /// <returns>
        ///     The validation errors.
        /// </returns>
        [NotNull, Pure]
        IDictionary<string, IList<object>> GetAllErrors();

#if TASKSUPPORT
        /// <summary>
        ///     Updates information about errors in the specified property.
        /// </summary>
        /// <param name="propertyName">The specified property name.</param>
        Task Validate([NotNull]string propertyName);

        /// <summary>
        ///     Updates information about all errors.
        /// </summary>
        Task ValidateAll();
#else
        /// <summary>
        ///     Updates information about errors in the specified property.
        /// </summary>
        /// <param name="propertyName">The specified property name.</param>
        IOperationResult Validate([NotNull]string propertyName);

        /// <summary>
        ///     Updates information about all errors.
        /// </summary>
        IOperationResult ValidateAll();
#endif

        /// <summary>
        ///     Clears errors for a property.
        /// </summary>
        /// <param name="propertyName">The name of the property</param>
        void ClearErrors([NotNull]string propertyName);

        /// <summary>
        ///     Clears the all errors.
        /// </summary>
        void ClearErrors();

        /// <summary>
        ///     Determines whether the current model is valid.
        /// </summary>
        /// <returns>
        ///     If <c>true</c> current model is valid, otherwise <c>false</c>.
        /// </returns>
        [Pure]
        bool IsValid();

        /// <summary>
        ///     Creates a new validator that is a copy of the current instance.
        /// </summary>
        /// <returns>
        ///     A new validator that is a copy of this instance.
        /// </returns>
        IValidator Clone();
    }
}